package top 

import chisel3._
import chisel3.util._
import chisel3.experimental._

import uart2._
import puf2._ 
import common._

class top extends Module{
    val io = IO(new Bundle{
        val led         =   new PUF_LED_Ports
        val test_out    =   Output(Bool())
        val uart        =   new Uart_Ports
        val puf_out     =   new PUF_Top_Output_Ports 
    })

    val M_puf           =   Module(new puf_top)
    val M_control       =   Module(new control)
    val M_uart_tx       =   Module(new uart_tx)
    val M_uart_rx       =   Module(new uart_rx)

    val rst_n           =   Wire(Reset())
    rst_n               :=  Mux(reset.asBool, false.B, true.B)

//  _______   _______ .______    __    __    _______ 
// |       \ |   ____||   _  \  |  |  |  |  /  _____|
// |  .--.  ||  |__   |  |_)  | |  |  |  | |  |  __  
// |  |  |  ||   __|  |   _  <  |  |  |  | |  | |_ | 
// |  '--'  ||  |____ |  |_)  | |  `--'  | |  |__| | 
// |_______/ |_______||______/   \______/   \______| 

    io.led.led          :=  M_control.io.led
    val M_Clk_Divider   =   Module(new clk_divider(2, 2))
    M_Clk_Divider.io.clk    :=  io.puf_out.Clk_out.asClock
    M_Clk_Divider.io.rst_p  :=  reset.asBool
    io.test_out             :=  M_Clk_Divider.io.clk_div.asBool

//  __    __       ___      .______     .___________.      .___________.___   ___ 
// |  |  |  |     /   \     |   _  \    |           |      |           |\  \ /  / 
// |  |  |  |    /  ^  \    |  |_)  |   `---|  |----`______`---|  |----` \  V  /  
// |  |  |  |   /  /_\  \   |      /        |  |    |______|   |  |       >   <   
// |  `--'  |  /  _____  \  |  |\  \----.   |  |               |  |      /  .  \  
//  \______/  /__/     \__\ | _| `._____|   |__|               |__|     /__/ \__\ 
                               
    // input
    M_uart_tx.io.clk            :=      clock 
    M_uart_tx.io.rst_n          :=      rst_n
    M_uart_tx.io.tx_data        :=      M_control.io.uart_tx_data
    M_uart_tx.io.tx_data_valid  :=      M_control.io.uart_tx_valid
    // output
    M_control.io.uart_tx_ready  :=      M_uart_tx.io.tx_data_ready
    io.uart.uart_tx             :=      M_uart_tx.io.tx_pin

//  __    __       ___      .______     .___________.      .______     ___   ___ 
// |  |  |  |     /   \     |   _  \    |           |      |   _  \    \  \ /  / 
// |  |  |  |    /  ^  \    |  |_)  |   `---|  |----`______|  |_)  |    \  V  /  
// |  |  |  |   /  /_\  \   |      /        |  |    |______|      /      >   <   
// |  `--'  |  /  _____  \  |  |\  \----.   |  |           |  |\  \----./  .  \  
//  \______/  /__/     \__\ | _| `._____|   |__|           | _| `._____/__/ \__\ 
                                                                              
    // input
    M_uart_rx.io.clk            :=      clock 
    M_uart_rx.io.rst_n          :=      rst_n
    M_uart_rx.io.rx_data_ready  :=      M_control.io.uart_rx_ready
    M_uart_rx.io.rx_pin         :=      io.uart.uart_rx
    // output
    M_control.io.uart_rx_data   :=      M_uart_rx.io.rx_data
    M_control.io.uart_rx_valid  :=      M_uart_rx.io.rx_data_valid

// .______    __    __   _______ 
// |   _  \  |  |  |  | |   ____|
// |  |_)  | |  |  |  | |  |__   
// |   ___/  |  |  |  | |   __|  
// |  |      |  `--'  | |  |     
// | _|       \______/  |__|     

    M_puf.io.out                <>      io.puf_out
    M_puf.io.ctr.puf_in_valid   :=      M_control.io.puf_in_valid
    M_puf.io.ctr.puf_data_in    :=      M_control.io.puf_data_in
    M_puf.io.ctr.puf_out_ready  :=      M_control.io.puf_out_ready
    M_puf.io.ctr.puf_wl_ena     :=      M_control.io.puf_wl_ena 
    M_puf.io.ctr.puf_write_ena  :=      M_control.io.puf_write_ena
    
    M_control.io.puf_in_ready   :=      M_puf.io.ctr.puf_in_ready
    M_control.io.puf_out_valid  :=      M_puf.io.ctr.puf_out_valid
    M_control.io.puf_data_out   :=      M_puf.io.ctr.puf_data_out
}